package com.example.project.controller.project;

import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.nio.file.Files;
import java.util.List;
import java.util.Map;
import java.util.Optional;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ContentDisposition;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import com.example.project.annotation.Log;
import com.example.project.core.controller.BaseController;
import com.example.project.core.domain.AjaxResult;
import com.example.project.core.page.TableDataInfo;
import com.example.project.domain.AttachmentUpdateRequest;
import com.example.project.entity.Attachment;
import com.example.project.entity.User;
import com.example.project.enums.BusinessType;
import com.example.project.exception.attachment.ResourceNotFoundException;
import com.example.project.service.AttachmentService;
import com.example.project.utils.RedmineUtils;
import com.example.project.utils.file.FileUtils;
import com.example.project.utils.file.MimeTypeUtils;

/**
 * 附件，存储系统中所有上传的文件信息Controller
 * 
 * @author ruoyi
 * @date 2025-09-23
 */
@Controller
@RequestMapping("/project/attachments")
public class AttachmentController extends BaseController {

	private static final Logger logger = LoggerFactory.getLogger(AttachmentController.class);

	private String prefix = "project/attachments";

	@Autowired
	private AttachmentService attachmentService;

	// 显示附件信息
	@GetMapping("/{id}")
	public ResponseEntity<Object> showAttachment(@PathVariable Long id, @RequestParam(required = false) String filename,
			HttpServletRequest request) {

		try {
			// 查找附件
			Attachment attachment = attachmentService.selectAttachmentById(id);
			if (attachment == null) {
				return ResponseEntity.notFound().build();
			}

			// 验证文件名
			if (filename != null && !filename.equals(attachment.getFilename())) {
				return ResponseEntity.notFound().build();
			}

			// 检查文件可读性
			if (!FileUtils.isFileReadable(attachment.getDiskFilename())) {
				return ResponseEntity.notFound().build();
			}

			// 处理容器附件列表（类似Ruby中的分页逻辑）
			if (attachment.getContainerType() != null
					&& attachmentService.hasAttachment(attachment.getContainerType())) {
				List<Attachment> containerAttachment = attachmentService
						.getContainerAttachment(attachment.getContainerType());
				int currentIndex = containerAttachment.indexOf(attachment);
				if (currentIndex >= 0) {
					// 创建分页信息（简化实现）
//					Map<String, Object> paginationInfo = Map.of("total", containerAttachment.size(), "current",
//							currentIndex + 1, "perPage", 1);
					// 可以将分页信息添加到响应中
				}
			}

			// 根据文件类型返回不同响应
//			if (attachmentService.isDiffFile(attachment)) {
//				// 差异文件处理
//				String diffContent = attachmentService.readDiffContent(attachment);
//				String diffType = determineDiffType(request);
//
//				// 保存用户偏好设置（类似Ruby逻辑）
//				User currentUser = userService.getCurrentUser();
//				if (currentUser != null && currentUser.isLoggedIn()) {
//					String userDiffType = userService.getUserPreference(currentUser, "diff_type");
//					if (userDiffType == null || !userDiffType.equals(diffType)) {
//						userService.setUserPreference(currentUser, "diff_type", diffType);
//					}
//				}
//
//				return ResponseEntity.ok(createDiffResponse(diffContent, diffType));
//			} else 
			if (FileUtils.isTextFile(attachment.getContentType()) && attachment.getFilesize() <= getMaxDisplaySize()) {
				// 文本文件处理
				String textContent = FileUtils.readFileContent(attachment.getFilePath());
				return ResponseEntity.ok(createTextResponse(textContent));
			} else if (FileUtils.isImageFile(attachment.getContentType())) {
				// 图片文件处理
				return ResponseEntity.ok(createImageResponse(attachment));
			} else {
				// 其他文件类型
				return ResponseEntity.ok(createOtherResponse(attachment));
			}

		} catch (Exception e) {
			return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
		}
	}

	// 下载附件
	@GetMapping("/{id}/download")
	public ResponseEntity<byte[]> downloadAttachment(@PathVariable Long id, HttpServletResponse response) {

		try {
			Attachment attachment = attachmentService.selectAttachmentById(id);
			if (attachment == null) {
				return ResponseEntity.notFound().build();
			}

			// 文件可读性检查
			if (!FileUtils.isFileReadable(attachment.getFilePath())) {
				logger.error(
						"Cannot send attachment, " + attachment.getFilePath() + " does not exist or is unreadable.");
				return ResponseEntity.notFound().build();
			}

			attachmentService.incrementDownloadCount(attachment);

			// ETag缓存验证
			String etag = attachment.getDigest();
			if (isCached(etag, response)) {
				return ResponseEntity.status(HttpStatus.NOT_MODIFIED).build();
			}

			// 准备文件下载
			File file = new File(attachment.getDiskFilename());
			byte[] fileContent = Files.readAllBytes(file.toPath());

			HttpHeaders headers = new HttpHeaders();
			headers.setContentType(MediaType.parseMediaType(detectContentType(attachment)));
			headers.setContentDispositionFormData("attachment",
					getContentDispositionFilename(attachment.getFilename()));
			headers.setETag("\"" + etag + "\"");

			// 设置安全策略头（类似Ruby中的content-security-policy）
			headers.set("Content-Security-Policy", "default-src 'none'; style-src 'unsafe-inline'; sandbox");

			// 处理文件处置方式
			String disposition = disposition(attachment);
			if ("inline".equals(disposition)) {
				headers.setContentDisposition(ContentDisposition.inline().filename(attachment.getFilename()).build());
			}

			return ResponseEntity.ok().headers(headers).body(fileContent);

		} catch (Exception e) {
			return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
		}
	}

	// 生成缩略图
	@GetMapping("/{id}/thumbnail")
	public ResponseEntity<byte[]> thumbnail(@PathVariable Long id, @RequestParam(required = false) Integer size) {

		try {
			Attachment attachment = attachmentService.selectAttachmentById(id);
//					.orElseThrow(() -> new ResourceNotFoundException("Attachment not found"));

			// 可读性检查
			if (!FileUtils.isFileReadable(attachment.getFilePath())) {
				return ResponseEntity.notFound().build();
			}

			// 生成缩略图
			Optional<File> thumbnail = FileUtils.generateThumbnail(attachment.getFilePath(), size);
			if (thumbnail.isEmpty()) {
				return ResponseEntity.notFound().build();
			}

			File thumbnailFile = thumbnail.get();
			byte[] thumbnailContent = Files.readAllBytes(thumbnailFile.toPath());

			HttpHeaders headers = new HttpHeaders();
			headers.setContentType(MediaType.parseMediaType(detectContentType(attachment, true)));
			headers.setContentDispositionFormData("attachment",
					getContentDispositionFilename(attachment.getFilename()));

			// ETag缓存验证
			String etag = thumbnailFile.getName();
			if (isCached(etag, null)) { // 简化处理，实际需要response参数
				return ResponseEntity.status(HttpStatus.NOT_MODIFIED).build();
			}

			return ResponseEntity.ok().headers(headers).body(thumbnailContent);

		} catch (ResourceNotFoundException e) {
			return ResponseEntity.notFound().build();
		} catch (IOException e) {
			return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
		}
	}

	// 上传附件
	@PostMapping("/upload")
	public ResponseEntity<?> uploadAttachment(@RequestParam(required = false) String filename,
			@RequestParam(required = false) String content_type, HttpServletRequest request) {

		// 检查Content-Type（类似Ruby中的媒体类型检查）
		String mediaType = request.getContentType();
		if (mediaType == null || !mediaType.equals("application/octet-stream")) {
			return ResponseEntity.status(HttpStatus.NOT_ACCEPTABLE).build();
		}

		try {
			// 获取当前用户
			User currentUser = getUser();
			if (currentUser == null) {
				return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build();
			}

			// 创建附件对象
			Attachment attachment = new Attachment();
			attachment.setAuthorId(getUserId());

			// 处理文件名（类似Ruby中的逻辑）
			if (filename != null && !filename.trim().isEmpty()) {
				attachment.setFilename(filename.trim());
			} else {
				// 生成随机文件名（类似Redmine::Utils.random_hex(16)）
				attachment.setFilename(RedmineUtils.generateHex(16));
			}

			// 处理内容类型
			if (content_type != null && !content_type.trim().isEmpty()) {
				attachment.setContentType(content_type.trim());
			}

			// 处理文件内容（类似Ruby中的raw_request_body逻辑）
			byte[] fileContent = getRawRequestBody(request);
			attachment.setFilesize((long) fileContent.length);

			// 保存附件
			Attachment saved = attachmentService.insertAttachment(attachment);
			if (saved.getId() > 0) {
				// 返回创建成功的响应
				return ResponseEntity.status(HttpStatus.CREATED).body(createUploadResponse(attachment));
			} else {
				// 处理验证错误（类似Ruby中的render_validation_errors）
				return ResponseEntity.status(HttpStatus.BAD_REQUEST)
						.body(createValidationErrors("Failed to save attachment"));
			}

		} catch (Exception e) {
			return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(createErrorResponse(e.getMessage()));
		}
	}

	// 批量下载附件
	@GetMapping("/container/{objectType}/{objectId}/download-all")
	public ResponseEntity<byte[]> downloadAllAttachment(@PathVariable String objectType, @PathVariable Long objectId) {

		try {
			// 查找容器对象
			Object container = findContainer(objectType, objectId);
			if (container == null) {
				return ResponseEntity.notFound().build();
			}

			// 查找可下载的附件（暂不实现）
			// List<Attachment> attachments = attachmentService.findDownloadableAttachment(container);
			List<Attachment> attachments = List.of(); // 临时实现

			// 检查批量下载大小限制
			long totalSize = attachments.stream().mapToLong(Attachment::getFilesize).sum();

			long maxBulkSize = getBulkDownloadMaxSize();
			if (totalSize > maxBulkSize) {
				return ResponseEntity.status(HttpStatus.PAYLOAD_TOO_LARGE)
						.body("文件大小超过限制".getBytes());
			}

			// 生成ZIP文件（暂不实现）
			// byte[] zipData = attachmentService.createAttachmentZip(attachments);
			byte[] zipData = new byte[0]; // 临时实现
			String zipFilename = objectType.toLowerCase() + "-" + objectId + "-attachments.zip";

			HttpHeaders headers = new HttpHeaders();
			headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
			headers.setContentDispositionFormData("attachment", zipFilename);

			return ResponseEntity.ok().headers(headers).body(zipData);

		} catch (Exception e) {
			return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
		}
	}

	// 更新附件信息
	@PutMapping("/{id}")
	public ResponseEntity<?> updateAttachment(@PathVariable Long id,
			@RequestBody AttachmentUpdateRequest updateRequest) {

		try {
			Attachment attachment = attachmentService.selectAttachmentById(id);
			if (attachment == null) {
				throw new ResourceNotFoundException("Attachment not found");
			}

			// 更新权限检查
			// if (!authorizationService.canEditAttachment(attachment)) {
			// return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
			// }

			// 更新附件信息
			attachment.setFilename(updateRequest.getFilename());
			// attachment.setDescription(updateRequest.getDescription());

			attachmentService.updateAttachment(attachment);

			return ResponseEntity.ok(createUpdateResponse(attachment));

		} catch (ResourceNotFoundException e) {
			return ResponseEntity.notFound().build();
		} catch (Exception e) {
			return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(createValidationErrors(e.getMessage()));
		}
	}

	// 删除附件
//	@DeleteMapping("delete/{id}")
//	public ResponseEntity<?> deleteAttachment(@PathVariable Long id) {
//
//		try {
//			Attachment attachment = attachmentService.getById(id);
//			if (attachment == null) {
//				return ResponseEntity.notFound().build();
//			}
//
//			// 处理容器关联（类似Ruby中的逻辑）
////			Object container = attachment.getContainerType();
////			if (container != null) {
////				// 检查容器是否支持日志记录（类似Ruby中的respond_to?(:init_journal)）
////				if (container instanceof JournalAware) {
////					User currentUser = userService.getCurrentUser();
////					((JournalAware) container).initJournal(currentUser);
////				}
////
////				// 通过容器删除以触发关联回调（类似Ruby中的container.attachments.delete）
////				boolean deleted = attachmentService.deleteFromContainer(attachment, container);
////				if (!deleted) {
////					return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
////				}
////			} else {
//				// 直接删除附件
//				boolean deleted = attachmentService.deleteAttachmentById(attachment.getId()) > 0;
//				if (!deleted) {
//					return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
//				}
////			}
//
//			// 返回成功响应（支持多种格式，类似Ruby中的respond_to）
//			return ResponseEntity.ok().build();
//
//		} catch (Exception e) {
//			return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
//		}
//	}

	// 辅助方法
	private boolean isCached(String etag, HttpServletResponse response) {
		// 简化实现，实际需要完整的ETag验证逻辑
		return false;
	}

	private String detectContentType(Attachment attachment) {
		return detectContentType(attachment, false);
	}

	private String detectContentType(Attachment attachment, boolean isThumb) {
		String contentType = attachment.getContentType();
		if (contentType == null || contentType.isEmpty() || "application/octet-stream".equals(contentType)) {
			contentType = MimeTypeUtils.detectMimeType(attachment.getFilename());
			if (contentType == null) {
				contentType = "application/octet-stream";
			}
		}

		if (isThumb && "application/pdf".equals(contentType)) {
			// PDF预览图存储为PNG格式
			contentType = "image/png";
		}

		return contentType;
	}

	private String getContentDispositionFilename(String filename) {
		// 处理文件名编码，确保浏览器正确显示
		try {
			return new String(filename.getBytes("UTF-8"), "ISO-8859-1");
		} catch (UnsupportedEncodingException e) {
			return filename;
		}
	}

	private byte[] getRawRequestBody(HttpServletRequest request) throws IOException {
		return request.getInputStream().readAllBytes();
	}

	private Object findContainer(String objectType, Long objectId) {
		// 根据对象类型和ID查找容器对象
		try {
			Class<?> klass = Class.forName(
					"com.example.project.entity." + objectType.substring(0, 1).toUpperCase() + objectType.substring(1));
			return attachmentService.findContainerById(klass, objectId);
		} catch (ClassNotFoundException e) {
			return null;
		}
	}

	private Object createTextResponse(String textContent) {
		return Map.of("type", "text", "content", textContent);
	}

	private Object createImageResponse(Attachment attachment) {
		return Map.of("type", "image", "filename", attachment.getFilename(), "contentType", attachment.getContentType(),
				"size", attachment.getFilesize());
	}

	private Object createOtherResponse(Attachment attachment) {
		return Map.of("type", "file", "filename", attachment.getFilename(), "contentType", attachment.getContentType(),
				"size", attachment.getFilesize());
	}

	private Object createUploadResponse(Attachment attachment) {
		return Map.of("id", attachment.getId(), "filename", attachment.getFilename(), "contentType",
				attachment.getContentType(), "size", attachment.getFilesize());
	}

	private Object createErrorResponse(String message) {
		return Map.of("error", message);
	}

	private Object createUpdateResponse(Attachment attachment) {
		return Map.of("id", attachment.getId(), "filename", attachment.getFilename());
	}

	private Object createValidationErrors(String message) {
		return Map.of("errors", List.of(message));
	}

	private long getMaxDisplaySize() {
		return 1024 * 1024; // 默认1MB
	}

	private long getBulkDownloadMaxSize() {
		return 10 * 1024 * 1024; // 默认10MB
	}

	// 文件处置方式（类似Ruby中的disposition方法）
	private String disposition(Attachment attachment) {
		// if (attachmentService.isPdfFile(attachment)) {
		// 	return "inline";
		// } else {
			return "attachment";
		// }
	}

	@RequiresPermissions("system:attachments:view")
	@GetMapping()
	public String attachments() {
		return prefix + "/attachments";
	}

	/**
	 * 查询附件，存储系统中所有上传的文件信息列表
	 */
	@RequiresPermissions("system:attachments:list")
	@PostMapping("/list")
	@ResponseBody
	public TableDataInfo list(Attachment tAttachment) {
		startPage();
		List<Attachment> list = attachmentService.selectAttachmentList(tAttachment);
		return getDataTable(list);
	}

	/**
	 * 新增附件，存储系统中所有上传的文件信息
	 */
	@RequiresPermissions("system:attachments:add")
	@GetMapping("/add")
	public String add() {
		return prefix + "/add";
	}

	/**
	 * 新增保存附件，存储系统中所有上传的文件信息
	 */
	@RequiresPermissions("system:attachments:add")
	@Log(title = "附件，存储系统中所有上传的文件信息", businessType = BusinessType.INSERT)
	@PostMapping("/add")
	@ResponseBody
	public AjaxResult addSave(Attachment tAttachment) {
		return toAjax(attachmentService.insertAttachment(tAttachment).getId());
	}

	/**
	 * 修改附件，存储系统中所有上传的文件信息
	 */
	@RequiresPermissions("system:attachments:edit")
	@GetMapping("/edit/{id}")
	public String edit(@PathVariable("id") Long id, ModelMap mmap) {
		Attachment tAttachment = attachmentService.selectAttachmentById(id);
		mmap.put("tAttachment", tAttachment);
		return prefix + "/edit";
	}

	/**
	 * 修改保存附件，存储系统中所有上传的文件信息
	 */
	@RequiresPermissions("system:attachments:edit")
	@Log(title = "附件，存储系统中所有上传的文件信息", businessType = BusinessType.UPDATE)
	@PostMapping("/edit")
	@ResponseBody
	public AjaxResult editSave(Attachment tAttachment) {
		return toAjax(attachmentService.updateAttachment(tAttachment));
	}

	/**
	 * 删除附件，存储系统中所有上传的文件信息
	 */
	@RequiresPermissions("system:attachments:remove")
	@Log(title = "附件，存储系统中所有上传的文件信息", businessType = BusinessType.DELETE)
	@PostMapping("/remove")
	@ResponseBody
	public AjaxResult remove(String ids) {
		return toAjax(attachmentService.deleteAttachmentByIds(ids));
	}

	/**
	 * 删除单个附件
	 */
	@RequiresPermissions("system:attachments:remove")
	@Log(title = "附件，存储系统中所有上传的文件信息", businessType = BusinessType.DELETE)
	@DeleteMapping("/delete/{id}")
	@ResponseBody
	public AjaxResult deleteAttachment(@PathVariable("id") Long id) {
			Attachment attachment = attachmentService.selectAttachmentById(id);
			if (attachment == null) {
				return AjaxResult.error("附件不存在");
			}
			
			// 删除物理文件
//			if (attachment.getDiskFilename() != null) {
//				java.io.File file = new java.io.File(attachment.getDiskFilename());
//				if (file.exists()) {
//					file.delete();
//				}
//			}

			// 删除数据库记录
			int result = attachmentService.deleteAttachmentById(id);
			return toAjax(result);
	}

}